package cn.wizzer.app.user.modules.service.impl;

import cn.wizzer.app.user.modules.models.GroupMember;
import cn.wizzer.app.user.modules.models.constant.ChatConstant;
import cn.wizzer.app.user.modules.models.vo.GroupMemberVo;
import cn.wizzer.app.user.modules.services.GroupLogService;
import cn.wizzer.app.user.modules.services.GroupMemberService;
import cn.wizzer.app.user.modules.services.UserService;
import cn.wizzer.framework.util.Result;
import cn.wizzer.framework.base.model.enums.BizExceptionEnum;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import com.alibaba.dubbo.config.annotation.Service;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.util.List;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = GroupMemberService.class)
public class GroupMemberServiceImpl extends BaseServiceImpl<GroupMember> implements GroupMemberService {
    public GroupMemberServiceImpl(Dao dao) {
        super(dao);
    }

    private static final Log log = Logs.get();

    @Inject
    private GroupLogService groupLogService;
    @Inject
    private UserService userService;
    @Inject
    private CommonDBService dbService;
    @Inject
    private RedisService redisService;



    @Aop(TransAop.READ_COMMITTED)
    @Override
    public void addMember(String userId, String groupId) {
        //查询群里以前是否存在该成员，若不存在则新增
        GroupMember groupMember = this.fetch(Cnd.where("userId", "=", userId).and("groupId", "=", groupId));
        if (groupMember == null) {
            //添加群成员
            groupMember = new GroupMember();
            groupMember.setGroupId(groupId);
            groupMember.setUserId(userId);
            groupMember.setSort(1);
            this.insert(groupMember);
        } else {
            log.error("该用户已入群，不要重复添加");
            Result.breakWith("该用户已入群，不要重复添加");
        }

        // 测试使用，正式打包删除
//        String content = "测试消息。正式环境删除。UserNickName: " + userService.fetch(userId).getNickName() + "!";
//        groupLogService.groupSend(userId, groupId, content, MsgTypeEnum.TEXT, OprTypeEnum.ADDED, false);
    }


    @Override
    public void delMember(String userId, String groupId) {
        log.error("移除群成员,群id：" + groupId + ",用户id：" + userId);
        GroupMember groupMember = this.fetch(Cnd.where("userId", "=", userId).and("groupId", "=", groupId));
        this.delete(groupMember.getId());
        // 同时清空redis
        String redisKey = ChatConstant.UG + ":" + groupMember.getUserId() + ":" + groupMember.getGroupId();
        redisService.del(redisKey);
    }

    @Override
    public void delMember(String groupId) {
        log.error("移除所有群成员,群id：" + groupId);
        List<GroupMember> list = this.list(groupId);
        for (GroupMember groupMember : list) {
            this.delMember(groupMember.getUserId(), groupId);
        }
    }



    @Override
    public Pagination list(String userId, String groupId, int pageNumber, int pageSize) {
        GroupMember groupMember = this.fetch(Cnd.where("groupId", "=", groupId).and("userId", "=", userId).and("delFlag", "=", 0));
        if (groupMember == null) {
            Result.breakWith(BizExceptionEnum.NOT_IN_THE_GROUP);
        }
        Sql sql = Sqls.create("SELECT u.id as userId, u.nickName, u.userName,u.headPicture ,gm.manager " +
                "FROM group_member gm " +
                "LEFT JOIN `user` u ON gm.userId = u.id " +
                "WHERE gm.groupId = @groupId " +
                "AND gm.delFlag = 0 " +
                "ORDER BY gm.sort,gm.manager DESC");
        sql.setParam("groupId", groupId);
        return dbService.listPage(GroupMemberVo.class, pageNumber, pageSize, sql.toString());
    }

    @Override
    public List<GroupMember> list(String groupId) {
        return this.query(Cnd.where("groupId", "=", groupId));
    }

    @Override
    public List<GroupMember> listOnline(String groupId) {
        StringBuffer sb = new StringBuffer();
        sb.append("select g.userId from ball_gold.group_member g where g.groupId='").append(groupId);
        sb.append("' and g.userId in(select u.id from user u where u.isOnline='1')");
        return dbService.list(GroupMember.class, sb.toString());
    }

    @Override
    public List<GroupMember> listMember(String userId) {
        return this.query(Cnd.where("userId", "=", userId));
    }

    @Override
    public Pagination listPage(int pageNumber, int pageSize, String groupName, String userKeyword, String[] searchDate) {
        Sql sql = Sqls.create("SELECT i.groupName, u.nickName, u.userName, gm.id, gm.ctAt, gm.userId,gm.manager " +
                "FROM group_member gm ");
        Sql countSql = Sqls.create("SELECT COUNT(1) FROM group_member gm ");
        Sql joinSql = Sqls.create("LEFT JOIN user u ON u.id = gm.userId " +
                "LEFT JOIN group_info i ON i.id = gm.groupId " +
                "$condition ");
        Cnd cnd = Cnd.where("gm.delFlag", "=", 0);
        if (Strings.isNotBlank(groupName)) {
            cnd.and("i.groupName", "=", groupName);
        }
        if (Strings.isNotBlank(userKeyword)) {
            cnd.and(Cnd.exps("u.nickName", "=", userKeyword)
                    .or("u.userName", "=", userKeyword));
        }
        if (searchDate != null && searchDate.length > 0) {
            cnd.and("gm.ctAt", ">=", Times.d2TS(Times.D(searchDate[0])));
            cnd.and("gm.ctAt", "<=", Times.d2TS(Times.D(searchDate[1])));
        }
        joinSql.setCondition(cnd);
        sql.appendSourceSql(joinSql.toString());
        sql.appendSourceSql("ORDER BY gm.ctAt DESC");
        countSql.appendSourceSql(joinSql.toString());
        return dbService.listPage(GroupMemberVo.class, pageNumber, pageSize, sql.toString(), countSql.toString());
    }


    @Aop(TransAop.READ_COMMITTED)
    @Override
    public void batchAdd(String[] userIds, String groupId) {
        for (String userId : userIds) {
            addMember(userId, groupId);
        }
    }
}
